﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using GingerBeard.Utilities;

namespace GingerBeard.IDL
{
	public partial class IDL
	{
		#region Internal Loading Framework
		public static IDL Create(String filename)
		{
			using (FileStream s = new FileStream(filename, FileMode.Open, FileAccess.Read))
			{
				IDL idl = Create(s);
				idl.SourceFilename = filename;
				return idl;
			}
		}

		public static IDL Create(Stream stream)
		{
			using (StreamReader r = new StreamReader(stream))
			{
				return Create(r);
			}
		}

		public static IDL Create(TextReader reader)
		{
			using (XmlReader r = XmlReader.Create(reader))
			{
				return (IDL)XmlParser.LoadNode(r, null, nodeRecords);
			}
		}
		#endregion

		#region Object Definitions
		private static XmlParser.NodeRecord[] nodeRecords = 
		{
			new XmlParser.NodeRecord("idl", ProcessGenericNode<IDL>),
			new XmlParser.NodeRecord("variable", ProcessVariable),
			new XmlParser.NodeRecord("object", ProcessGenericNode<IDLObject>),
			new XmlParser.NodeRecord("namespace", ProcessGenericNode<IDLNamespace>),
			new XmlParser.NodeRecord("enum", ProcessEnum),
			new XmlParser.NodeRecord("types", ProcessGenericNode<IDLTypes>),
			new XmlParser.NodeRecord("type", ProcessType),
			new XmlParser.NodeRecord("iflanguage", ProcessGenericNode<IDLIfLanguage>),
			new XmlParser.NodeRecord("container", ProcessContainer)
		};

		private static void ProcessCommonNodeAttributes(XmlReader r, Node node)
		{
			IDLNode n = node as IDLNode;
			n.Name = r.GetAttribute("name");

			int alignment;
			n.Alignment = IDLNode.DefaultAlignment;
			if (int.TryParse(r.GetAttribute("alignment"), out alignment))
				n.Alignment = alignment;

			n.Obsolete = r.GetAttribute("obsolete");
		}

		private static Node ProcessGenericNode<T>(XmlReader r, Node parent) where T : Node, new()
		{
			T obj = new T();
			ProcessCommonNodeAttributes(r, obj);
			return obj;
		}

		private static Node ProcessVariable(XmlReader r, Node parent)
		{
			IDLVariable newObj = new IDLVariable();
			ProcessCommonNodeAttributes(r, newObj);
			newObj.Type = r.GetAttribute("type");
			return newObj;
		}

		private static Node ProcessType(XmlReader r, Node parent)
		{
			IDLType newObj = new IDLType();
			ProcessCommonNodeAttributes(r, newObj);
			newObj.ActualType = r.GetAttribute("actualType");
			return newObj;
		}

		private static Node ProcessEnum(XmlReader r, Node parent)
		{
			IDLEnum newObj = new IDLEnum();
			ProcessCommonNodeAttributes(r, newObj);
			newObj.Values = r.GetAttribute("values");
			return newObj;
		}

		private static Node ProcessContainer(XmlReader r, Node parent)
		{
			IDLContainer newObj = new IDLContainer();
			ProcessCommonNodeAttributes(r, newObj);
			newObj.Type = r.GetAttribute("type");
			return newObj;
		}

		

		#endregion
	}
}
